#include "MySQLClient.h"
#include "Logger.h"
#include <stdio.h>
namespace myNameSpace
{
    MySQLClient::MySQLClient()
    {
        init();
    }

    MySQLClient::~MySQLClient()
    {
        mysql_close(&_mysqlConnection);
    }

    void MySQLClient::init()
    {
        MYSQL *pMysqlConnection = mysql_init(&_mysqlConnection);
        if (!pMysqlConnection)
        {
            moqi::LOG_ERROR("mysql_init failed.");
            exit(EXIT_FAILURE);
        }
    }

    void MySQLClient::connect(const string &host, const string &user, const string &password, const string &database, unsigned short port)
    {
        MYSQL *pMysqlConnection = mysql_real_connect(&_mysqlConnection, host.c_str(), user.c_str(), password.c_str(), database.c_str(), port, nullptr, 0);
        if (!pMysqlConnection)
        {
            moqi::LOG_ERROR("%s.", mysql_error(&_mysqlConnection));
            exit(EXIT_FAILURE);
        }
    }

    bool MySQLClient::writeOperationQuery(const string &sql)
    {
        int ret = mysql_real_query(&_mysqlConnection, sql.c_str(), sql.size());
        if (ret)
        {
            moqi::LOG_ERROR("(%d, %s.)", mysql_errno(&_mysqlConnection), mysql_error(&_mysqlConnection));
            return false;
        }
        moqi::LOG_INFO("Query OK, %d rows affected.", mysql_affected_rows(&_mysqlConnection));
        return true;
    }

    vector<vector<string>> MySQLClient::readOperationQuery(const string &sql)
    {
        int ret = mysql_real_query(&_mysqlConnection, sql.c_str(), sql.size());
        if (ret)
        {
            moqi::LOG_ERROR("(%d, %s.)", mysql_errno(&_mysqlConnection), mysql_error(&_mysqlConnection));
            mysql_close(&_mysqlConnection);
            exit(EXIT_FAILURE);
        }
        MYSQL_RES *pResult = mysql_use_result(&_mysqlConnection);
        if (!pResult)
        {
            moqi::LOG_ERROR("(%d, %s.)", mysql_errno(&_mysqlConnection), mysql_error(&_mysqlConnection));
            mysql_close(&_mysqlConnection);
            exit(EXIT_FAILURE);
        }
        unsigned int cols = mysql_num_fields(pResult);
        vector<vector<string>> result;
        unsigned int rows = 0;
        while (MYSQL_ROW mysqlRow = mysql_fetch_row(pResult))
        {
            vector<string> row;
            for (unsigned int i = 0; i < cols; ++i)
            {
                row.emplace_back(mysqlRow[i]);
            }
            result.emplace_back(row);
            ++rows;
        }
        moqi::LOG_INFO("%u row(s) in set.", rows);
        return result;
    }

    bool MySQLClient::appendData(const string &tableName,
                                 const string &dataFiled, const string &data,
                                 const string &keyFiled, const string &key)
    // 给表table中Namefiled_key=key的一行中，filed_data列添加数据data
    {
        char buffer[200]; // 确保缓冲区足够大！
        sprintf(buffer, "UPDATE %s SET %s=%s WHERE %s = %s;", tableName.c_str(),
                dataFiled.c_str(), data.c_str(), keyFiled.c_str(), key.c_str());
        return writeOperationQuery(string(buffer));
    }

    string MySQLClient::findData(const string &tableName,
                                          const string &dataFiled, 
                                          const string &keyFiled, const string &key)
    { // 从tableName表中找到dataFiled，条件是keyFiled=key，如果存在返回盐值
        // 如果不存在返回空字符串
        char buffer[200]; // 确保缓冲区足够大！
        sprintf(buffer, "SELECT %s FROM %s WHERE %s = '%s'",
                dataFiled.c_str(), tableName.c_str(), keyFiled.c_str(), key.c_str());
        vector<vector<string>> res = readOperationQuery(string(buffer));
        if (!res.empty())
        {
            return res[0][0];
        }
        else
        {
            return "";
        }
    }
} // end of namespace myNameSpace
